/*
 ------------------------------------------------------------------------------
 Copyright (C) 2013 Eternal Games.

 This file is part of the EternalTech source code.

 The EternalTech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The EternalTech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the EternalTech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// anim_animation.cpp - animation manager
//


#include "anim_local.h"


#define ANIMATIONS_HASH_SIZE			(MAX_ANIMATIONS >> 2)

static animation_t *	anim_animationsHashTable[ANIMATIONS_HASH_SIZE];
static animation_t *	anim_animations[MAX_ANIMATIONS];
static int				anim_numAnimations;


/*
 ==============================================================================

 ANIMATION LOADING

 ==============================================================================
*/


/*
 ==================
 
 ==================
*/
static animation_t *Anim_LoadAnimation (const char *name){

	animation_t	*animation;
	defData_t	*defData;
	script_t	*script;
	token_t		token;
	uint		hashKey;

	// See if already loaded
	hashKey = Str_HashKey(name, ANIMATIONS_HASH_SIZE, false);

	for (animation = anim_animationsHashTable[hashKey]; animation; animation = animation->nextHash){
		if (!Str_ICompare(animation->name, name))
			return animation;
	}

	// Find the definition
	defData = glqDefManager->FindDef(DEF_ANIMATION, name);
	if (!defData)
		return NULL;

	// Load the script text
	script = glqParser->LoadScriptMemory(defData->sourceFile, defData->textString, defData->textLength, defData->sourceLine);
	if (!script)
		return NULL;

	glqParser->SetScriptFlags(script, SF_ALLOWPATHNAMES);

	// Allocate the animation
	if (anim_numAnimations == MAX_ANIMATIONS)
		G_Error("Anim_LoadAnimation: MAX_ANIMATIONS hit");

	anim_animations[anim_numAnimations++] = animation = (animation_t *)glqMemory->ClearedAlloc(sizeof(animation_t), game.memoryTag);

	// Fill it in
	Str_Copy(animation->name, name, sizeof(animation->name));
	animation->size = sizeof(animation_t);

	// Skip the opening brace
	glqParser->ExpectTokenString(script, &token, "{", true);

	// TODO: parse it here

	// Skip the closing brace
	glqParser->ExpectTokenString(script, &token, "}", true);

	// Free the script text
	glqParser->FreeScript(script);

	// Add to hash table
	animation->nextHash = anim_animationsHashTable[hashKey];
	anim_animationsHashTable[hashKey] = animation;

	return animation;
}

/*
 ==================
 Anim_RegisterAnimation
 ==================
*/
animation_t *Anim_RegisterAnimation (const char *name){

	return Anim_LoadAnimation(name);
}


/*
 ==============================================================================

 CONSOLE COMMANDS

 ==============================================================================
*/


/*
 ==================
 
 ==================
*/
static void Anim_ListAnimations_f (){

}


/*
 ==============================================================================

 INITIALIZATION & SHUTDOWN

 ==============================================================================
*/


/*
 ==================
 Anim_InitAnimations
 ==================
*/
void Anim_InitAnimations (){

	// Add commands
	if (game.isClient)
		glqCmdSystem->AddCommand("listClientAnimations", Anim_ListAnimations_f, "Lists loaded animations", NULL);
	else
		glqCmdSystem->AddCommand("listServerAnimations", Anim_ListAnimations_f, "Lists loaded animations", NULL);

	// Register the animation definition type
	glqDefManager->RegisterType(DEF_ANIMATION, "animation", "models", ".anim", "listAnimationDefs", "printAnimationDef");

	// Load all the animation definitions
	glqDefManager->LoadDefs(DEF_ANIMATION, false);
}

/*
 ==================
 
 ==================
*/
void Anim_ShutdownAnimations (){

	animation_t	*animation;
	int			i;

	// Remove commands
	if (game.isClient)
		glqCmdSystem->RemoveCommand("listClientAnimations");
	else
		glqCmdSystem->RemoveCommand("listServerAnimations");

	// Free all the animations
	for (i = 0; i < anim_numAnimations; i++){
		animation = anim_animations[i];

		// TODO: free any necessary allocations here

		glqMemory->Free(animation);
	}

	// Clear animation list
	glqMemory->Fill(anim_animationsHashTable, 0, sizeof(anim_animationsHashTable));
	glqMemory->Fill(anim_animations, 0, sizeof(anim_animations));

	anim_numAnimations = 0;
}